import 'dart:io';
import 'dart:async';
import 'package:fixnum/fixnum.dart';
import 'package:github_client_app/env/env.dart';
import 'generated/disnode.pb.dart';

class TcpUtil {
  static Socket? _socket;
  static final String _tcpIp = Env.envConfig.envTcpIp;
  static final int _tcpPort = Env.envConfig.envTcpPort;
  // 连接超时时间
  static const Duration _connectTimeout = Duration(seconds: 5);
  // 心跳间隔时间
  static const Duration _heartTime = Duration(seconds: 60);
  // 心跳定时器
  static Timer? _timer;
  // 重连次数
  static const int _reconnectCount = 3;
  // 当前重连次数
  static int _curReconnectCount = 0;

  // 初始化
  static init() async {
    try {
      _socket =
          await Socket.connect(_tcpIp, _tcpPort, timeout: _connectTimeout);
      _socket!.listen(_onData,
          onError: _onError, onDone: _doneHandler, cancelOnError: false);
      // 重连次数清0
      _curReconnectCount = 0;
      // print("tcp连接成功");
      // 发送心跳包
      _keepAlive();
    } catch (e) {
      // print("连接socket出现异常，e=${e.toString()}");
      await _reconnect();
    }
  }

  // 重连
  static _reconnect() async {
    if (_curReconnectCount < _reconnectCount) {
      await socketClose();
      // print('重连中....');
      // print(_curReconnectCount);
      init();
      _curReconnectCount++;
    }
  }

  /// 发消息
  static _sendMsg(messageBytes) {
    try {
      _socket?.add(messageBytes);
    } catch (e) {
      // print("send发送消息异常：$e");
    }
  }

  // 心跳包
  static _keepAlive() {
    _timer?.cancel();
    _timer = null;
    _timer = Timer.periodic(_heartTime, (_) {
      // print('发送心跳包');
      // 组织消息
      final message = CommunicationMessage()
        ..messageType = MessageType.HeartBeatType
        ..nodeName = 'flutter'
        ..timestamp = Int64(DateTime.now().millisecondsSinceEpoch)
        ..messageHeartbeat = MessageHeartBeat(
            taskCount: Int64(DateTime.now().millisecondsSinceEpoch));
      // 将消息编码为字节数组
      final messageBytes = message.writeToBuffer();
      _sendMsg(messageBytes);
    });
  }

  // 注册消息
  static void register() {
    // print('发送注册消息');
    // 组织消息
    final message = CommunicationMessage()
      ..messageType = MessageType.RegisterType
      ..nodeName = 'flutter'
      ..timestamp = Int64(DateTime.now().millisecondsSinceEpoch)
      ..messageRegister = MessageRegister();
    // 将消息编码为字节数组
    final messageBytes = message.writeToBuffer();
    _sendMsg(messageBytes);
  }

  // 注销消息
  static void deRegister() {
    // print('发送注销消息');
    // 组织消息
    final message = CommunicationMessage()
      ..messageType = MessageType.DeRegisterType
      ..nodeName = 'flutter'
      ..timestamp = Int64(DateTime.now().millisecondsSinceEpoch)
      ..messageDeRegister = MessageDeRegister();
    // 将消息编码为字节数组
    final messageBytes = message.writeToBuffer();
    _sendMsg(messageBytes);
  }

  // 推送任务
  static void pushTask(MessagePushTask msg) {
    // print('发送推送任务消息');

    // 组织消息
    final message = CommunicationMessage()
      ..messageType = MessageType.PushTaskType
      ..nodeName = 'flutter'
      ..timestamp = Int64(DateTime.now().millisecondsSinceEpoch)
      ..messagePushTask = msg;
    // 将消息编码为字节数组
    final messageBytes = message.writeToBuffer();
    _sendMsg(messageBytes);
  }

  // 接收任务消息
  static void acceptTask(MessageAcceptTask msg) {
    // print('发送接收任务消息');
    // 组织消息
    final message = CommunicationMessage()
      ..messageType = MessageType.AcceptTaskType
      ..nodeName = 'flutter'
      ..timestamp = Int64(DateTime.now().millisecondsSinceEpoch)
      ..messageAcceptTask = msg;
    // 将消息编码为字节数组
    final messageBytes = message.writeToBuffer();
    _sendMsg(messageBytes);
  }

  // 获取数据
  static _onData(newData) {
    final responseMessage = CommunicationMessage.fromBuffer(newData);
    // print('接收到tcp消息: $responseMessage');
  }

  // 异常
  static _onError(error, StackTrace trace) {
    // print("捕获tcp连接异常：error=$error，trace=${trace.toString()}");
    _reconnect(); // 重连
  }

  // 断开连接
  static _doneHandler() {
    _socket?.destroy();
    _socket = null;
    _timer?.cancel();
    _timer = null;
    // print("断开连接");
  }

  // 关闭
  static socketClose() async {
    await _socket?.close();
    // print("关闭连接");
  }
}
